package com.cans.lightning.business.lowcode.service.impl;

import com.cans.lightning.business.core.service.UUIDAutoGen;
import com.cans.lightning.business.lowcode.dao.api.IAppFormDataDao;
import com.cans.lightning.business.lowcode.dto.AppFormRowDataDto;
import com.cans.lightning.business.lowcode.dto.AppFormFieldValueDto;
import com.cans.lightning.business.lowcode.dto.AppFormDto;
import com.cans.lightning.business.lowcode.enums.AppFormSysField;
import com.cans.lightning.business.lowcode.enums.FieldTypeEnum;
import com.cans.lightning.business.lowcode.manager.form.AppFormBeanManager;
import com.cans.lightning.business.lowcode.manager.form.bean.AppFormBean;
import com.cans.lightning.business.lowcode.service.api.IAppFormDataService;
import com.cans.lightning.business.lowcode.service.api.IAppFormDefinitionService;
import com.google.common.base.Joiner;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.tuple.Pair;
import org.beetl.sql.core.SQLManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 应用信息
 *
 * @author shencan
 * @date 2020/6/14 20:53
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class AppFormDataServiceImpl implements IAppFormDataService {
    private static final Logger logger = LoggerFactory.getLogger(AppFormDataServiceImpl.class);

    @Resource
    private SQLManager sqlManager;
    @Resource(name = "appFormDataDao")
    private IAppFormDataDao appFormDataDao;
    @Resource
    private IAppFormDefinitionService appFormDefinitionService;
    @Resource
    private AppFormBeanManager appFormBeanManager;
    @Resource
    private UUIDAutoGen idAutoGen;

    @Override
    public void saveOrUpdate(AppFormRowDataDto formDataDto) {
        AppFormDto formDefinitionServiceInfo = appFormDefinitionService.getInfo(formDataDto.getFormId());
        Pair<String, Map<String, Object>> sqlPair = this.getInsertSql(formDefinitionServiceInfo.getMainTable().getDbTableName(), formDataDto.getFieldValue());
        sqlManager.executeUpdate(sqlPair.getLeft(), sqlPair.getValue());

    }

    @Override
    public void deleteById(AppFormRowDataDto formDataDto) {
        AppFormDto formDefinitionServiceInfo = appFormDefinitionService.getInfo(formDataDto.getFormId());
        Map<String, String> param = new HashMap<>(1);
        String[] idArr = formDataDto.getDataId().split(",");
        int i = 0;
        for (String id : idArr) {
            param.put("id" + "_" + i++, id);
        }
        appFormDataDao.deleteFormData(formDefinitionServiceInfo.getMainTable().getDbTableName(), param);
    }

    @Override
    public List<Map> getPageData(AppFormRowDataDto formDataDto) {
        AppFormDto formDefinitionServiceInfo = appFormDefinitionService.getInfo(formDataDto.getFormId());
        List<Map> objects = appFormDataDao.selectDataList(formDefinitionServiceInfo.getMainTable().getDbTableName());
        return objects;
    }

    @Override
    public AppFormBean createOrEdit(AppFormRowDataDto formDataDto) {
        return appFormBeanManager.getFormBean(formDataDto.getFormId());
    }

    private Pair<String, Map<String, Object>> getInsertSql(String dbTableName, List<AppFormFieldValueDto> fieldValues) {
        Map<String, Object> params = Maps.newLinkedHashMap();
        params.put(AppFormSysField.ID, idAutoGen.nextID());
        params.put(AppFormSysField.CREATE_TIME, new Date());
        params.put(AppFormSysField.LAST_CHANGE_TIME, new Date());

        for (AppFormFieldValueDto fieldValue : fieldValues) {
            params.put(fieldValue.getDbFieldName(), this.parseToDbValue(fieldValue));
        }
        Set<String> fieldNames = params.keySet();
        String sql = "INSERT INTO " + dbTableName + " ( " + Joiner.on(",").join(fieldNames) + " ) " + "VALUES " + "( " + Joiner.on(",").join(fieldNames.stream().map(i -> String.format("#{%s}", i)).collect(Collectors.toList())) + " )";

        return Pair.of(sql, params);
    }

    private Object parseToDbValue(AppFormFieldValueDto fieldValue) {
        if (fieldValue.getValue() == null) {
            return null;
        }
        FieldTypeEnum fieldTypeEnum = FieldTypeEnum.getByKey(fieldValue.getDbFieldDataType());
        if (fieldTypeEnum == null) {
            throw new IllegalStateException("Unexpected value: " + fieldValue.getDbFieldDataType());
        }
        Object dbValue = fieldValue.getValue();
        switch (fieldTypeEnum) {
            case VARCHAR:
                break;
            case INT:
                break;
            case DATE:
                SimpleDateFormat smf = new SimpleDateFormat("yyyy-MM-dd");
                try {
                    dbValue = smf.parse(fieldValue.getValue());
                } catch (ParseException e) {
                    dbValue = null;
                    logger.error("日期格式化失败,value" + fieldValue.getValue(), e);
                }
                break;
            case DATE_TIME:
                break;
            case FILE:
                break;
            case DECIMAL:
                break;
            default:
                throw new IllegalStateException("Unexpected value: " + fieldValue.getDbFieldDataType());
        }
        return dbValue;
    }

}
